package top.kikt.book.core.handlers

import org.jsoup.nodes.Document
import top.kikt.book.core.entity.BookMetaEntity
import top.kikt.book.core.entity.ChapterEntity
import top.kikt.book.core.entity.ChapterMetaEntity
import top.kikt.book.core.handlers.common.BaseBookHandler
import top.kikt.book.core.handlers.common.CommonBookHandler
import top.kikt.book.util.bookText
import top.kikt.book.util.metaContentWithProperty
import top.kikt.book.util.resolveBySrcUrl
import java.nio.charset.Charset

class `23Qb` : BaseBookHandler(), CommonBookHandler {

    override fun forceCharset(): Charset? {
        return Charset.forName("gbk")
    }

    override fun headers(): Map<String, String> {
        return mapOf(
            "Referer" to "https://www.23qb.com/",
            "accept-language" to "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        ) + chromeHeaders()
    }

    override val host: String
        get() = "www.23qb.com"

    override fun parseBookMeta(document: Document, url: String): BookMetaEntity {
        val author = document.metaContentWithProperty("og:novel:author")
        val name = document.metaContentWithProperty("og:novel:book_name")
        val cover = document.metaContentWithProperty("og:image")
        val desc = document.metaContentWithProperty("og:description")
        return BookMetaEntity(name, url, url, author, cover, desc)
    }

    override fun parseChapterMeta(document: Document, menuUrl: String): List<ChapterMetaEntity> {
        val list = document.getElementById("chapterList")
        val li = list?.select("li") ?: return emptyList()

        return li.mapIndexed { index, it ->
            val a = it.select("a")[0]
            val url = a.attr("href").resolveBySrcUrl(menuUrl)
            val name = a.text()
            ChapterMetaEntity(name, index, url, a)
        }
    }

    private fun getNextPageUrl(doc: Document?): String? {
        if (doc == null) {
            return null
        }
        val scripts = doc.getElementsByTag("script")
        for (script in scripts) {
            val text = script.data()
            if (text.contains("nextpage")) {
                val regex = Regex("""var nextpage="(/book/.+.html)";""")
                val pageSuffix = regex.findAll(text).firstOrNull()?.groupValues?.get(1)

                if (pageSuffix?.contains("_") == true) {
                    return pageSuffix
                } else {
                    return null
                }
            }
        }
        return null
    }

    override fun parseChapter(chapterMetaEntity: ChapterMetaEntity): ChapterEntity? {
        val contentList = ArrayList<String>()

        var doc = chapterMetaEntity.toDocument(charset)
        val content = doc?.select("#TextContent p")?.bookText() ?: return null
        contentList.add(content)

        var page = 1

        while (true) {
            val url = getNextPageUrl(doc) ?: break
            val nextDocUrl = url.resolveBySrcUrl(chapterMetaEntity.url)
            doc = getUrlDocument(nextDocUrl)
            val nextContent = doc?.select("#TextContent p")?.bookText() ?: break
            contentList.add(nextContent)
            page++
        }

        logger.info("Chapter ${chapterMetaEntity.name} has $page pages")

        return chapterMetaEntity.toChapterMetaEntity(contentList.joinToString("\n"))
    }

    override fun watermark(): Map<Regex, String> {
        return mapOf(
            Regex("铅笔小说 23qb.com") to ""
        )
    }
}